#include "document.h"
#include "gameObjects/physicsobject.h"
#include "gameObjects/visualobject.h"
#include "gameObjects/actor.h"
#include "levelObjects/level.h"

Document::Document(QObject *parent) :
    QObject(parent)
{
	
}

QPointer<AbstractGameObject> Document::createActor(const QString &name)
{
	QString actorName = name;
	if(actorName == "")
	{
		actorName = QString("Actor%1").arg(m_actors.size());
	}

    QPointer<AbstractGameObject> newActor = new Actor(this, actorName);
	initGameObjectConnections(newActor);
	add(newActor);
	return newActor;
}

QPointer<AbstractGameObject> Document::createVisualObject(const QString &name,
	QPointer<AbstractGameObject> parentActor)
{
	QPointer<Actor> actor = qobject_cast<Actor*>(parentActor);
	QString voName = name;
	if(voName == "")
	{
		voName = QString("VisualObject%1").arg(actor->visualObjects().count());
	}

	QPointer<AbstractGameObject> newVisualObject = new VisualObject(parentActor, voName);
	initGameObjectConnections(newVisualObject);
	add(newVisualObject);
	return newVisualObject;
}

QPointer<AbstractGameObject> Document::createPhysicsObject( QPointer<AbstractGameObject> parentVisualObject )
{
	QPointer<AbstractGameObject> newPhysicsObject = new PhysicsObject(parentVisualObject);
	initGameObjectConnections(newPhysicsObject);
	add(newPhysicsObject);
	return newPhysicsObject;
}

void Document::add( QPointer<AbstractGameObject> go )
{
	if(go->parent() == this)
	{
		m_actors << go;
	}
	else if(go->parentGameObject()->type() == GOT_Actor)
	{
		QPointer<Actor> actor = qobject_cast<Actor*>(go->parentGameObject());
		actor->addVisualObject(go);
	}

	m_allGameObjects << go;

	emit gameObjectAdded(go);
}

void Document::remove( QPointer<AbstractGameObject> go )
{
	if(go->parent() == this)
	{
		m_actors.removeOne(go);
	}
	else if(go->parentGameObject()->type() == GOT_Actor)
	{
		QPointer<Actor> actor = qobject_cast<Actor*>(go->parentGameObject());
		actor->removeVisualObject(go);
	}

	m_allGameObjects.removeOne(go);

	emit gameObjectRemoved(go);
}

void Document::onObjectDataChanged()
{
	QPointer<AbstractGameObject> go = qobject_cast<AbstractGameObject*>(sender());
	Q_ASSERT(go);
	emit objectDataChanged(go);
}

void Document::initGameObjectConnections( QPointer<AbstractGameObject> go )
{
	connect(go, &AbstractGameObject::dataChanged, 
		this, &Document::onObjectDataChanged);
}

const Document::AllGameObjects& Document::allGameObjects() const
{
	return m_allGameObjects;
}

QPointer<LevelObjects::AbstractLevelObject> Document::createLevel( const QString& name )
{
	QString levelName = name;
	if(levelName == "")
	{
		levelName = QString("Level%1").arg(m_levels.size());
	}

	QPointer<LevelObjects::AbstractLevelObject> newLevel = new LevelObjects::Level(this, levelName);
	m_levels << newLevel;
	emit levelCreated(newLevel);
	return newLevel;
}

void Document::deleteLevel( QPointer<LevelObjects::AbstractLevelObject> level )
{
	m_levels.removeOne(level);
	emit levelDeleted(level);
}

const Document::Actors& Document::actors() const
{
	return m_actors;
}

QPointer<LevelObjects::AbstractLevelObject> Document::levelByGuid( const QUuid& guid )
{
	QPointer<LevelObjects::AbstractLevelObject> result;

	foreach(QPointer<LevelObjects::AbstractLevelObject> level, m_levels)
	{
		if(level->guid() == guid)
		{
			result = level;
			break;
		}
	}

	return result;
}


